﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using System.Collections;
using System.Text.RegularExpressions;

namespace SmashedApples.Utils
{
    /// <summary>
    /// Static class to hold utility methods.
    /// </summary>
    public static class SmashedUtils
    {
        /// <summary>
        /// Converts a Byte[] to a String
        /// </summary>
        /// <param name="byteArray">byte Array to convert to string</param>
        /// <returns>resulting string</returns>
        public static string ByteArrayToString(Byte[] byteArray)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            string output = encoding.GetString(byteArray);
            return output;
        }

        /// <summary>
        /// Takes a List&lt;String&gt; and converts it to a string delimited by the specified
        /// delimiter.  If the delimiter is omitted, then the values in the string will be 
        /// separated by a comma.
        /// </summary>
        /// <param name="valueList">List&lt;String&gt;</param>
        /// <returns>The list of the values delimited by a comma as a string</returns>
        public static String ListToString(List<String> valueList)
        {
            return ListToString(valueList, null);
        }

        /// <summary>
        /// Takes a string delimited by the a comma and converts it to a List&lt;String&gt;.
        /// </summary>
        /// <param name="value">The list of the values delimited by a comma as a string</param>
        /// <returns>List&lt;String&gt;The list of the values delimited by a comma as a string</returns>
        public static List<String> StringToList(String value)
        {
            return StringToList(value, null);
        }

        /// <summary>
        /// Takes a string delimited by the specified delimiter and converts it to a List&lt;String&gt;.
        /// </summary>
        /// <param name="value">The list of the values delimited by a comma as a string</param>
        /// <param name="delimiter">Delimiter used to separate each element in the string by</param>
        /// <returns>List&lt;String&gt;The list of the values delimited by a comma as a string</returns>
        public static List<String> StringToList(String value, String delimiter)
        {
            List<String> returnValue = new List<string>();

            if (String.IsNullOrEmpty(delimiter))
            {
                delimiter = ",";
            }

            if (!String.IsNullOrEmpty(value))
            {
                String[] values = Regex.Split(value, delimiter);
                for (int i = 0; i < values.Length; i++)
                {
                    returnValue.Add(values[i].Trim());
                }
            }

            return returnValue;
        }

        /// <summary>
        /// Takes a List&lt;String&gt; and converts it to a string delimited by the specified
        /// delimiter.  If the delimiter is omitted, then the values in the string will be 
        /// separated by a comma.
        /// </summary>
        /// <param name="valueList">List&lt;String&gt; to convert to a delimited string</param>
        /// <param name="delimiter">String to delimit values by like ",", etc.</param>
        /// <returns>The list of the values delimited by the specified delimiter as a string</returns>
        public static String ListToString(List<String> valueList, String delimiter)
        {
            String returnValue = null;

            if (String.IsNullOrEmpty(delimiter))
            {
                delimiter = ",";
            }

            if (valueList != null)
            {
                if (valueList.Count > 0)
                {
                    foreach (String value in valueList)
                    {
                        if (valueList.Count == 1)
                        {
                            returnValue = value;
                        }
                        else
                        {
                            returnValue = AppendToString(value, returnValue, delimiter);
                        }
                    }
                }
            }

            return returnValue;
        }

        /// <summary>
        /// Appends a string of text to a specified string of text and will delimit by a comma.
        /// This method handles the appendTo which is null and will not prepend a comma to the
        /// string.
        /// </summary>
        /// <param name="textToAppend">Text to append to an existing string</param>
        /// <param name="appendTo">String can be null or contain a value</param>
        /// <returns>The text specified in the textToAppend will be concatenated to the 
        /// appendTo string delimited by a comma.  If the initial value of the appendTo 
        /// string is null, the text specified in the textToAppend will simply be copied 
        /// and returned</returns>
        /// <example>
        /// String myText = WGCUtil.AppendToString("Molly", "Suzy,John");
        /// // myText will be equal to Suzy,John,Molly 
        /// String myText = WGCUtil.AppendToString("Suzy,John", null);
        /// // myText will be equal to Suzy,John 
        /// </example>
        public static String AppendToString(String textToAppend, String appendTo)
        {
            return AppendToString(textToAppend, appendTo, ",");
        }

        /// <summary>
        /// Appends a string of text to a specified string of text and will delimit by a the value 
        /// designated.  If the delimiter is null, it will default to a comma.
        /// This method handles the appendTo which is null and will not prepend the delimiter to the
        /// string.
        /// </summary>
        /// <param name="textToAppend">Text to append to an existing string</param>
        /// <param name="appendTo">String can be null or contain a value</param>\
        /// <param name="delimiter">Delimiter to use in appending a string to an existing string</param>
        /// <returns>The text specified in the textToAppend will be concatenated to the 
        /// appendTo string delimited by a comma.  If the initial value of the appendTo 
        /// string is null, the text specified in the textToAppend will simply be copied 
        /// and returned</returns>
        /// <example>
        /// String myText = WGCUtil.AppendToString("Molly", "Suzy John", " ");
        /// // myText will be equal to Suzy John Molly 
        /// String myText = WGCUtil.AppendToString("Suzy John", null, null);
        /// // myText will be equal to Suzy John 
        /// </example>
        public static String AppendToString(String textToAppend, String appendTo, String delimiter)
        {
            if (!String.IsNullOrEmpty(textToAppend))
            {
                if (String.IsNullOrEmpty(appendTo))
                {
                    appendTo = textToAppend;
                }
                else
                {
                    appendTo += delimiter + textToAppend;
                }
            }

            return appendTo;
        }

      

        /// <summary>
        /// Searches a DataTable and sets and indicator specifying whether a row(s) were found.
        /// </summary>
        /// <param name="dataTable">DataTable to search</param>
        /// <param name="columnName">Column name to search for</param>
        /// <param name="columnValue">Column value to search for</param>
        /// <returns>boolean indicating if the column was found.</returns>
        public static Boolean SearchDataTable(DataTable dataTable, String columnName,
            String columnValue)
        {
            bool rowsFound = false;

            String searchCondition = columnName + " = '" + columnValue.Trim().ToUpper() + "'";
            DataRow[] dr = dataTable.Select(searchCondition);
            if (dr.Length > 0)
            {
                rowsFound = true;
            }

            return rowsFound;
        }

        /// <summary>
        /// Searches a DataTable and sets and indicator specifying whether a row(s) were found.
        /// </summary>
        /// <param name="dataTable">DataTable to search</param>
        /// <param name="columnName">Column name to search for</param>
        /// <param name="columnValue">Column value to search for</param>
        /// <returns>boolean indicating if the column was found.</returns>
        public static Boolean SearchDataTable(DataTable dataTable, String columnName,
            Decimal columnValue)
        {
            bool rowsFound = false;

            String searchCondition = columnName + " = " + columnValue;
            DataRow[] dr = dataTable.Select(searchCondition);
            if (dr.Length > 0)
            {
                rowsFound = true;
            }

            return rowsFound;
        }

       

       

        /// <summary>
        /// Serializes an Object to an XML String 
        /// </summary>
        /// <param name="inputObject">Object to be serialized and converted
        /// to a string</param>
        /// <returns>XML String representation of the object</returns>
        public static string ObjectToXMLString(object inputObject)
        {
            String returnVal;
            XmlSerializer serializer = new XmlSerializer(inputObject.GetType());
            using (StringWriter sw = new StringWriter())
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Encoding = Encoding.UTF8;
                settings.Indent = false;
                settings.OmitXmlDeclaration = true;
                settings.NewLineHandling = NewLineHandling.None;
                XmlWriter xw = XmlWriter.Create(sw, settings);
                serializer.Serialize(xw, inputObject);
                xw.Flush();
                returnVal = sw.ToString();
            }
            return returnVal;
        }

        /// <summary>
        /// .NET Native Rounding provides bankers rounding, i.e., to the nearest
        /// even digit.  For instances where you want 1-4 to round down and 5-9 to
        /// round up, this Round function will provide this functionality.
        /// </summary>
        /// <param name="input">The Number to Round</param>
        /// <param name="numOfDec">The Number of Resulting Decimal Places</param>
        /// <returns>The Rounded value</returns>
        public static decimal Round(decimal input, int numOfDec)
        {
            if (numOfDec < 0)
            {
                throw new ArgumentException("Number of decimal places must be 0 or greater");
            }

            //Shift the decimal to the right the number 
            //of digits they want to round to
            for (int i = 1; i <= numOfDec; i++)
            {
                input *= 10;
            }

            //Add/Subtract .5 to TRY to increase the number 
            //that is to the LEFT of the decimal
            if (input < 0)
            {
                input -= .5M;
            }
            else
            {
                input += .5M;
            }

            //Cut off the decimal, and you have the answer.
            input = (decimal)((Int64)input);

            //Shift the decimal back into its proper position
            for (int i = 1; i <= numOfDec; i++)
            {
                input /= 10;
            }

            return input;

        }

 
        public static Byte[] StringToByteArray(string input)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(input);
            return byteArray;
        }


        public static decimal Truncate(decimal input, decimal numOfDec)
        {
            if (numOfDec < 0)
            {
                throw new ArgumentException("Number of decimal places must be 0 or greater");
            }

            //Shift the decimal to the right the number 
            //of digits they want to round to
            for (int i = 1; i <= numOfDec; i++)
            {
                input *= 10;
            }

            input = Math.Truncate(input);

            //Shift the decimal back into its proper position
            for (int i = 1; i <= numOfDec; i++)
            {
                input /= 10;
            }

            return input;
        }


        public static object XMLStringToObject(string xmlString, Type objectType)
        {
            object o;
            XmlSerializer serializer = new XmlSerializer(objectType);

            using (System.IO.MemoryStream memoryStream = new
            System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlString)))
            {
                o = serializer.Deserialize(memoryStream);
            }

            return o;
        }

        

        private static bool FoundInList(String fieldValue, List<String> validValues)
        {
            bool foundInList = false;

            if (!String.IsNullOrEmpty(fieldValue) && validValues.Contains(fieldValue))
            {
                foundInList = true;
            }

            return foundInList;
        }

        private static bool FoundInList(String fieldValue, String validValues)
        {
            bool foundInList = false;

            if (!String.IsNullOrEmpty(fieldValue) && validValues.Contains(fieldValue))
            {
                foundInList = true;
            }

            return foundInList;
        }

        

    }
}
